package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domin.dto.ReplyDTO;
import com.tianji.learning.domin.po.InteractionQuestion;
import com.tianji.learning.domin.po.InteractionReply;
import com.tianji.learning.domin.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.query.ReplyPageQuery;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_CREATE_TIME;
import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_LIKED_TIME;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author author
 * @since 2023-09-08
 */
@Service
@RequiredArgsConstructor
@Transactional
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {

    private final InteractionQuestionMapper questionMapper;
    private final RabbitMqHelper mqHelper;
    private final UserClient userClient;
    private final RemarkClient remarkClient;

    @Override
    @Transactional
    public void saveReply(ReplyDTO replyDTO) {
        // 1.获取登录用户
        Long userId = UserContext.getUser();
        // 2.新增回答
        InteractionReply reply = BeanUtils.toBean(replyDTO, InteractionReply.class);
        reply.setUserId(userId);
        save(reply);
        // 3.累加评论数或者累加回答数
        // 3.1.判断当前回复的类型是否是回答
        boolean isAnswer = replyDTO.getAnswerId() == null;

        if (!isAnswer) {
            // 3.2.是评论，则需要更新上级回答的评论数量
            lambdaUpdate()
                    .setSql("reply_times = reply_times + 1")
                    .eq(InteractionReply::getId, replyDTO.getAnswerId())
                    .update();
        }
        // 3.3.尝试更新问题表中的状态、 最近一次回答、回答数量
        LambdaUpdateWrapper<InteractionQuestion> updateWrapper = Wrappers.<InteractionQuestion>lambdaUpdate()
                .set(isAnswer, InteractionQuestion::getLatestAnswerId, reply.getId())
                .setSql(isAnswer, "answer_times = answer_times + 1")
                .set(replyDTO.getIsStudent(), InteractionQuestion::getStatus, QuestionStatus.UN_CHECK.getValue())
                .eq(InteractionQuestion::getId, replyDTO.getQuestionId());
        questionMapper.update(null, updateWrapper);


        // 4.尝试累加积分
        if (replyDTO.getIsStudent()) {
            // 学生才需要累加积分
            mqHelper.send(
                    MqConstants.Exchange.LEARNING_EXCHANGE,
                    MqConstants.Key.WRITE_REPLY,
                    5);
        }
    }

    @Override
    public PageDTO<ReplyVO> queryReplyPage(ReplyPageQuery query, boolean forAdmin) {
        // 1.问题id和回答id至少要有一个，先做参数判断
        Long questionId = query.getQuestionId();
        Long answerId = query.getAnswerId();
        // 标记当前是查询问题下的回答
        boolean isQuestionId = questionId != null;

        // 2.分页查询reply

        Page<InteractionReply> page = lambdaQuery().eq(isQuestionId, InteractionReply::getQuestionId, questionId)
                .eq(InteractionReply::getAnswerId, isQuestionId ? 0L : answerId)
                .eq(!forAdmin, InteractionReply::getHidden, false)
                .page(query.toMpPage(new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false), new OrderItem(DATA_FIELD_NAME_CREATE_TIME, true)));

        List<InteractionReply> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        // 3.数据处理，需要查询：提问者信息、回复目标信息、当前用户是否点赞
        HashSet<Long> userId = new HashSet<>();
        HashSet<Long> targetReplyId = new HashSet<>();
        List<Long> bizIds = new ArrayList<>();
        // 3.1.获取提问者id 、回复的目标id、当前回答或评论id（统计点赞信息）
        for (InteractionReply record : records) {

            if (!record.getAnonymity() || forAdmin) {
                userId.add(record.getUserId());
            }

            if (record.getTargetUserId() != 0) {
                targetReplyId.add(record.getTargetReplyId());
            }
            bizIds.add(record.getId());
        }

        // 3.2.查询目标回复，如果目标回复不是匿名，则需要查询出目标回复的用户信息
        if (CollUtils.isNotEmpty(targetReplyId)) {
            List<InteractionReply> replies = listByIds(targetReplyId);

            List<Long> TUs = replies.stream().filter(Predicate.not(InteractionReply::getAnonymity).or(r -> forAdmin)).map(InteractionReply::getUserId).collect(Collectors.toList());

            userId.addAll(TUs);
        }


        // 3.4.查询用户点赞状态
        Set<Long> likesStatusIds = remarkClient.getLikesStatusByBizIds(bizIds);


        // 3.3.查询用户

        List<UserDTO> userDTOS = userClient.queryUserByIds(userId);
        Map<Long, UserDTO> userDTOHashMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, o -> o));


        // 4.处理VO
        ArrayList<ReplyVO> list = new ArrayList<>();

        for (InteractionReply r : records) {
            // 4.1.拷贝基础属性
            ReplyVO replyDTO = BeanUtils.copyBean(r, ReplyVO.class);
            list.add(replyDTO);
            UserDTO userDTO = userDTOHashMap.get(r.getUserId());
            // 4.2.回复人信息
            if (userDTO != null) {
                replyDTO.setUserId(r.getUserId());
                replyDTO.setUserType(userDTO.getType());
                replyDTO.setUserIcon(userDTO.getIcon());
                replyDTO.setUserName(userDTO.getName());
            }
            // 4.3.如果存在评论的目标，则需要设置目标用户信息
            if (CollUtils.isNotEmpty(targetReplyId)) {
                UserDTO TU = userDTOHashMap.get(r.getTargetUserId());

                if (TU != null) {
                    replyDTO.setTargetUserName(TU.getName());
                }
            }
            // 4.4.点赞状态
            replyDTO.setLiked(likesStatusIds.contains(r.getId()));
            // 4.5.点赞数量
            replyDTO.setLikedTimes(r.getLikedTimes());

        }
        return new PageDTO<>(page.getTotal(), page.getPages(), list);
    }

    @Override
    public void updateHidden(Long id, Boolean isHidden) {
        Long user = UserContext.getUser();//当前登录用户

        if (user == null) {
            throw new BadRequestException("未登录");
        }

        update(Wrappers.<InteractionReply>lambdaUpdate().eq(InteractionReply::getId, id).set(InteractionReply::getHidden, isHidden));
    }


}
